package com.sharp.socket.io.service;

import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIONamespace;
import com.sharp.authorization.constants.token.TokenItemConst;
import com.sharp.authorization.service.token.TokenService;
import com.sharp.framework.aop.publish.RedisPublishConfig;
import com.sharp.kernel.constant.dict.BoolDict;
import com.sharp.kernel.utils.ReflectionUtil;
import com.sharp.socket.io.bo.ChatMessage;
import com.sharp.socket.io.config.BaseLiveSocketIoConfig;
import com.sharp.socket.io.constant.ChatMessageConstant;
import com.sharp.socket.io.dao.mongo.po.TopicChatMessage;
import com.sharp.socket.io.dao.msyql.entity.ChatRoomMember;
import com.sharp.socket.io.dao.msyql.repository.ChatRoomMemberService;
import com.sharp.socket.io.service.chat.ChatMessageHistoryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;

/**
 * Title: SobotSendMessageService
 * Description: Copyright: Copyright (c) 2019 Company: BHFAE
 *
 * @author Sharp
 * @date 2020/9/22 17:26
 */
@Slf4j
@Service
public class SendMessageService {

    @Resource
    private ChatRoomMemberService chatRoomMemberService;
    @Resource
    private TokenService tokenService;
    @Resource
    private RedisPublishConfig redisPublishConfig;
    @Resource
    private ChatMessageHistoryService chatMessageHistoryService;

    private void fillChatMessage(SocketIOClient client, ChatMessage msg) {
        String token = client.getHandshakeData().getSingleUrlParam(BaseLiveSocketIoConfig.TOKEN);
        String userFace = tokenService.getItem(token, TokenItemConst.AVATAR.name(), String.class);
        String userName = tokenService.getItem(token, TokenItemConst.NICK_NAME.name(), String.class);
        if (StringUtils.isNotBlank(userName)) {
            msg.setUserId(userName);
        }
        if (StringUtils.isNotBlank(userFace)) {
            msg.setAvatar(userFace);
        }
        msg.setSessionId(client.getSessionId().toString());
    }

    public void broadcastMsg(ChatMessage chatMessage) {
        List<ChatRoomMember> memberList = chatRoomMemberService.getMemberListByRoomId(chatMessage.getRoomId());
        if (CollectionUtils.isNotEmpty(memberList)) {
            String uuid = UUID.randomUUID().toString();
            chatMessage.setOriginalMsgId(uuid);
            for (ChatRoomMember member : memberList) {
                publishMsg(ChatMessageConstant.CHAT, member.getUserId(), chatMessage);
            }
            chatMessage.setMsgId(uuid);
        }
    }

    public void publishMsg(String msgType, String target, ChatMessage msg) {
        TopicChatMessage topicChatMessage;
        if (StringUtils.equals(msgType, ChatMessageConstant.CHAT)) {
            topicChatMessage = saveUndeliveredTopicChatMessage(msgType, target, msg);
        } else {
            topicChatMessage = buildTopicChatMessage(msgType, target, msg);
        }
        publish(topicChatMessage);
    }

    private TopicChatMessage saveUndeliveredTopicChatMessage(String msgType, String target, ChatMessage msg) {
        TopicChatMessage topicChatMessage = buildTopicChatMessage(msgType, target, msg);
        topicChatMessage.setDelivered(BoolDict.NO.getValue());
        saveMessageHistory(topicChatMessage);
        return topicChatMessage;
    }

    private TopicChatMessage buildTopicChatMessage(String msgType, String target, ChatMessage msg) {
        TopicChatMessage topicChatMessage = ReflectionUtil.copy(msg, TopicChatMessage.class);
        if (StringUtils.isBlank(topicChatMessage.getMsgId())) {
            topicChatMessage.setMsgId(UUID.randomUUID().toString());
        }
        if (StringUtils.isBlank(topicChatMessage.getOriginalMsgId())) {
            topicChatMessage.setOriginalMsgId(topicChatMessage.getMsgId());
        }
        topicChatMessage.setTopic(msgType);
        topicChatMessage.setTargetId(target);
        topicChatMessage.setTimestamp(System.currentTimeMillis());
        return topicChatMessage;
    }

    public void publish(TopicChatMessage topicChatMessage) {
        log.debug("广播消息 {}", topicChatMessage);
        redisPublishConfig.publish(BaseLiveSocketIoConfig.buildChatMessageTopic(), topicChatMessage, true);
    }

    private void saveMessageHistory(TopicChatMessage topicChatMessage) {
        chatMessageHistoryService.save(topicChatMessage);
    }

    public void publishMsg(String target, ChatMessage msg) {
        publishMsg(ChatMessageConstant.CHAT, target, msg);
    }

    public void messageDelivered(TopicChatMessage topicChatMessage) {
        topicChatMessage.setDelivered(BoolDict.YES.getValue());
        saveMessageHistory(topicChatMessage);
    }

    public void sendSysMsg(SocketIONamespace namespace, String msg, String content) {
        String target = geTargetFromNamespace(namespace);
        TopicChatMessage topicChatMessage = buildTopicChatMessage(ChatMessageConstant.SYS, target, buildSysChatMessage(msg, content));
        namespace.getBroadcastOperations().sendEvent(topicChatMessage.getTopic(), topicChatMessage);
    }

    private String geTargetFromNamespace(SocketIONamespace namespace) {
        return namespace.getName().replaceFirst("/", "");
    }

    private ChatMessage buildSysChatMessage(String msg, String content) {
        ChatMessage message = new ChatMessage();
        message.setMsgType(msg);
        message.setContent(content);
        return message;
    }
}
